#include "cnarrfield.h"
#include "util.h"
#include <string>
#include <cassert>
#include <vector>
#include <iostream>
#include <sstream>
#include <memory.h>

using namespace std;
using namespace opsrc::stdf;

//template <typename T, int L, template <typename> class CONT >
template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
CnArrField<T,L,CONT>::CnArrField() {
}

template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
// template <typename T, int L, template <typename> class CONT >
CnArrField<T,L,CONT>::CnArrField(char *p, endian e, int elcount) {
	en = e;
	decode(p, elcount);
}

template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
// template <typename T, int L, template <typename> class CONT >
CnArrField<T,L,CONT>::~CnArrField() {
}


template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
// template <typename T, int L, template <typename> class CONT  >
void CnArrField<T,L,CONT>::decode(char* buf, int elemcount) {
	
	int curpos = 0;
	
	for ( int i=0; i < elemcount; i++ ) {
	
		// Determine if L=-1, the length is derived by reading the first byte of the 
		// pass-in buf character. If not, just read buf where the length is determined by 
		// L, the length of byte to read from buf.
		if (L<=0) {
			// first byte is the length
			int len = *(buf + curpos);
			if (len > 0 ) {
				char item[len+1];  // add one for char array termination
	    		::memcpy(item, /* offset by 1 byte */ buf+1, len);
	    		item[len] = '\0';  // assign last index as non-terminal
	    	
	    		T so(item);
	    		cont.push_back(so);
	    		
	    		// adjust count
	    		curpos += len +1;
	    		
	    		// update length or byte count of field
	    		blen += curpos;
			}
			else {
				blen++;
				T so("");
				cont.push_back(so);
				curpos++;
			}
			
		} 
		else {
			char item[L+1];  // add one for char array termination
	    	::memcpy(item, /* offset by 1 byte */ buf, blen);
	    	item[L] = '\0';  // assign last index as non-terminal
	   		T so(item);
	   		cont.push_back(so);
	   		curpos += L;
	   		blen += L;
		}	

	
	}
	
	
	
}

template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
// template <typename T, int L, template <typename> class CONT >
int CnArrField<T,L,CONT>::getByteCount() const {
	return blen;
}

template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
// template <typename T, int L, template <typename> class CONT >
const CONT<T> CnArrField<T,L,CONT>::getData() const {
	return cont;
}

template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
// template <typename T, int L, template <typename> class CONT >
string CnArrField<T,L,CONT>::arrayToString() {
	string result;
	
	unsigned int i =0;
	typename CONT<T>::const_iterator iter;
	
	// build char delimiter string. For example: 1, 2, 3, 4
	for ( iter= cont.begin();  iter != cont.end(); i++, iter++ ) {
		
	//	std::ostringstream stm;
	//    stm << *iter;		
	//	result += stm.str();
		result += (*iter);
		if (i+1 != cont.size())	result += ",";  // append separator
	}	
	return result;		
	
}

template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
// template <typename T, int L, template <typename> class CONT >
int CnArrField<T,L,CONT>::getCount() const {
	return cont.size();
}

template <typename T, int L, template <typename A, typename = std::allocator<A> >
class CONT >
// template <typename T, int L, template <typename> class CONT >
int CnArrField<T,L,CONT>::getTotalByteCount() const {
	return getByteCount();
}
	
